﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using AncientEmpires_025_132.ResourceString;

namespace AncientEmpires_025_132
{
    public class Battle : InVisibleGameEntity
    {
        #region properties của battle.
        // Trận đấu đang diễn ra?
        private bool _isFighting;
        public bool IsFighting
        {
            get { return _isFighting; }
            set { _isFighting = value; }
        }

        // Số lượng tất cả các đội trong 1 trận chiến
        private int _nGroup;
        public int NGroup
        {
            get { return _nGroup; }
            set { _nGroup = value; }
        }

        // Bản đồ cho trận chiến hiện tại.
        private MapWithCell _map;
        public MapWithCell Map
        {
            get { return _map; }
            set { _map = value; }
        }

        // Các building của map.
        private List<Building> _listBuilding;
        public List<Building> ListBuilding
        {
            get { return _listBuilding; }
            set { _listBuilding = value; }
        }

        // Danh sách tên nhóm của các đội: Group1, Group2, Group3, Group4.
        private List<TeamName> _listTeamName;
        public List<TeamName> ListTeamName
        {
            get { return _listTeamName; }
            set { _listTeamName = value; }
        }

        // Danh sách tên của các đội: Red, Green, Blue, Yellow.
        private List<NationName> _listNationName;

        public List<NationName> ListNationName
        {
            get { return _listNationName; }
            set { _listNationName = value; }
        }

        // Danh sách các loại team là người chơi hoặc máy tính: Player or Computer
        private List<TypeNation> _listTypeNation;
        public List<TypeNation> ListTypeNation
        {
            get { return _listTypeNation; }
            set { _listTypeNation = value; }
        }

        // Danh sách chứa các đội của trận chiến.
        private List<Nation> _listNation;
        public List<Nation> ListNation
        {
            get { return _listNation; }
            set { _listNation = value; }
        }

        // Số lượng lính tối đa của 1 đội trong trận chiến.
        private int _unitMaxCharacter;
        public int UnitMaxCharacter
        {
            get { return _unitMaxCharacter; }
            set { _unitMaxCharacter = value; }
        }

        // Số tiền của mỗi đội khi mới bắt đầu vào trận chiến.
        private int _maxMoney;
        public int MaxMoney
        {
            get { return _maxMoney; }
            set { _maxMoney = value; }
        }

        // Đếm số lần vẽ string new turn ra màn hình. Nếu = 30 thì ngưng vẽ
        private int countDrawNewTurn = 0;
        private System.Windows.Forms.Timer timerCount;
        private int countTime;

        private MyMouse mState;
        public MyMouse MState
        {
            get { return mState; }
            set { mState = value; }
        }
        #endregion

        #region
        public delegate void EventHandleBackMainMenu();
        public event EventHandleBackMainMenu EventBackMainMenu;
        public delegate void EventHandleExitGame();
        public event EventHandleExitGame EventExitGame;
        #endregion


        #region Xử lý các sự kiện khi nhận được.
        // Xử lý sự kiện thay đổi list building.
        void EventListBuildingChange(object obj)
        {
            if (obj is MapWithCell) // Do Map thay đổi list building.
            {
                for (int i = 0; i < ListNation.Count; i++)
                {
                    ListNation[i].BuildingOwner.Clear();
                    for (int j = 0; j < Map.ListBuilding.Count; j++)
                    {
                        if (ListNation[i].NationName == Map.ListBuilding[j].MyNationName)
                        {
                            ListNation[i].BuildingOwner.Add(Map.ListBuilding[j]);
                        }
                    }
                    if (ListNation[i].BuildingOwner.Count == 0)
                    {
                        ListNation.RemoveAt(i);
                        i--;
                    }
                }
                for (int i = 0; i < ListNation.Count; i++)
                {
                    bool flag = false;
                    for (int j = 0; j < ListNation[i].BuildingOwner.Count; j++)
                    {
                        if (ListNation[i].BuildingOwner[j] is Castle)
                        {
                            flag = true;
                            break;
                        }
                    }
                    if (!flag)
                    {
                        ListNation.RemoveAt(i);
                        i--;
                    }
                }
            }
            else // Do Nation thay đổi list building.
            {
                Map.ListBuilding.Clear();
                foreach (Nation nation in ListNation)
                {
                    foreach (Building building in nation.BuildingOwner)
                    {
                        Map.ListBuilding.Add(building);
                    }
                }
            }
        }
        // Xử lý sự kiện thay đổi list character.
        void EventListCharacterChange(object obj)
        {

            if (obj is MapWithCell) // Do Map thay đổi list character.
            {
                for (int i = 0; i < ListNation.Count; i++)
                {
                    ListNation[i].CharacterOwner.Clear();
                    for (int j = 0; j < Map.ListCharacter.Count; j++)
                    {
                        if (ListNation[i].NationName == Map.ListCharacter[j].MyNationName)
                        {
                            ListNation[i].CharacterOwner.Add(Map.ListCharacter[j]);
                        }
                    }
                }
            }
            else // Do Nation thay đổi list character.
            {
                Map.ListCharacter.Clear();

                foreach (Nation nation in ListNation)
                {
                    foreach (Character character in nation.CharacterOwner)
                    {
                        Map.ListCharacter.Add(character);
                    }
                }
            }
        }

        // Xử lý sự kiện mua character
        bool EventBuyCharacter(NationName nation, CharacterName name)
        {
            for (int i = 0; i < ListNation.Count; i++)
            {
                if (ListNation[i].NationName == nation)
                {
                    
                    int price = 0;
                    switch (name)
                    {
                        case CharacterName.King:
                            price = KingCharacter.Price;
                            break;
                        case CharacterName.Combative:
                            price = CombativeCharacter.Price;
                            break;
                        case CharacterName.Archer:
                            price = ArcherCharacter.Price;
                            break;
                        case CharacterName.Cavalry:
                            price = CavalryCharacter.Price;
                            break;
                        case CharacterName.Fairy:
                            price = FairyCharacter.Price;
                            break;
                        case CharacterName.Hydra:
                            price = HydraCharacter.Price;
                            break;
                        case CharacterName.Mage:
                            price = MageCharacter.Price;
                            break;
                        case CharacterName.Griffin:
                            price = GriffinCharacter.Price;
                            break;
                        case CharacterName.Soldier:
                            price = SoldierCharacter.Price;
                            break;
                    }
                    if (ListNation[i].Money >= price)
                    {
                        ListNation[i].Money -= price;
                        return true;
                    }
                    return false;
                }
            }
            return false;
        }

        // Xử lý sự kiện khi endturn 1 nation.
        void Map_EndturnNation()
        {
            if (CurrentCircle.IsChangeNation)
            {
                return;
            }
            countTime = 0;
            CurrentCircle.IsChangeNation = true;
            for (int i = 0; i < ListNation.Count; i++)
            {
                if (ListNation[i].NationName == CurrentCircle.NationCurrent)
                {
                    int index = (i + 1) % ListNation.Count;
                    CurrentCircle.NationCurrent = ListNation[index].NationName;
                    CurrentCircle.IsChangeNation = true;
                    ListNation[index].IncreaseMoney();
                    for (int j = 0; j < ListNation[i].CharacterOwner.Count; j++)
                    {
                        ListNation[i].CharacterOwner[j].IsEndTurn = false;
                    }
                    break;
                }
                else
                {
                    for (int j = 0; j < ListNation[i].CharacterOwner.Count; j++)
                    {
                        ListNation[i].CharacterOwner[j].IsEndTurn = false;
                    }
                }

            }
        }

        // Xử lý sự kiện khi panel cần update text.
        void Map_EventUpdateTextPanel()
        {
            switch (CurrentCircle.NationCurrent)
            {
                case NationName.Red:
                    Map.PanelGame.NationCurrent = "Red";
                    break;
                case NationName.Green:
                    Map.PanelGame.NationCurrent = "Green";
                    break;
                case NationName.Blue:
                    Map.PanelGame.NationCurrent = "Blue";
                    break;
                case NationName.Black:
                    Map.PanelGame.NationCurrent = "Black";
                    break;
                case NationName.None:
                    break;
            }
            foreach (Nation nation in ListNation)
            {
                if (nation.NationName == CurrentCircle.NationCurrent)
                {
                    Map.PanelGame.MoneyCurrent = nation.Money.ToString();
                    Map.PanelGame.NumCharacterCurrent = nation.CharacterOwner.Count.ToString() + "/" + this.UnitMaxCharacter.ToString();
                    Map.PanelGame.NumBuildingCurrent = nation.BuildingOwner.Count.ToString();
                    break;
                }
            }
        }

        // Proccess for back main menu
        void Map_EventBackMainMenu()
        {
            EventBackMainMenu();
        }

        // Proccess for back main menu
        void Map_EventExitGame()
        {
            EventExitGame();
        }

        // Proccess for back main menu
        void Map_EventPauseGame()
        {
            timerCount.Stop();
        }

        // Proccess for back main menu
        void Map_EventResumeGame()
        {
            timerCount.Start();
        }
        
        #endregion


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// Đếm thời gian lượt đi của 1 nation, nếu quá thời gian thì tự động end turn của nation đó.
        void timerCount_Tick(object sender, EventArgs e)
        {
            // Nếu đủ 3 phút
            if (countTime == 180)
            {
                Map_EndturnNation();
                return;
            }
            TimeSpan ts = TimeSpan.FromSeconds(180 - countTime);
            this.Map.PanelGame.TurnTimeCurrent = String.Format("{0:00}:{1:00}", ts.Minutes, ts.Seconds);
            countTime++;
        }

        public Battle(ContentManager content, GameWindow windowGame, string strMapXML)
        {
            this.Map = new MapWithCell(content, windowGame, strMapXML);
            Map.EndturnNation += new MapWithCell.EventHandlEndturnNation(Map_EndturnNation);
            Map.EventUpdateTextPanel += new MapWithCell.EventHandleUpdateTextPanel(Map_EventUpdateTextPanel);
            Map.EventBackMainMenu += new MapWithCell.EventHandleBackMainMenu(Map_EventBackMainMenu);
            Map.EventExitGame+= new MapWithCell.EventHandleExitGame(Map_EventExitGame);
            Map.EventPauseGame += new MapWithCell.EventHandlePauseGame(Map_EventPauseGame);
            Map.EventResumeGame += new MapWithCell.EventHandleResumeGame(Map_EventResumeGame);
            StringTextureCharacter.LoadContentTexture(content);
            countTime = 0;
            timerCount = new System.Windows.Forms.Timer();
            timerCount.Interval = 1000;
            timerCount.Tick += new EventHandler(timerCount_Tick);
            timerCount.Stop();
        }
        public Battle(ContentManager content, GameWindow windowGame, string strMapXML, List<NationName> nationName, 
                        List<TeamName> teamName, List<TypeNation> typeTeam, int[] teams, int moneys, int maxcharacter )
        {
            StringTextureCharacter.LoadContentTexture(content);
            NewSkirmishGame(content, windowGame, strMapXML, nationName, teamName, typeTeam, teams, moneys, maxcharacter);
        }

        public void NewSkirmishGame(ContentManager content, GameWindow windowGame, string mapName, SkirmishSetup skirmish)
        {
            List<TeamName> teamName = new List<TeamName>();
            List<TypeNation> typeNation = new List<TypeNation>();
            List<NationName> nationName = new List<NationName>();
            for (int i = 0; i < skirmish.ListNationSetup.Count; i++)
            {
                if (skirmish.ListNationSetup[i].TypeNationSetup != TypeNation.None)
                {
                    TeamName tempName = skirmish.ListNationSetup[i].TeamNameSetup;
                    TypeNation temptype = skirmish.ListNationSetup[i].TypeNationSetup;
                    teamName.Add(tempName);
                    typeNation.Add(temptype);
                    nationName.Add(skirmish.ListNationSetup[i].NationNameNationSetup);
                }
                
            }
            NewGame(content, windowGame, mapName, nationName, teamName, typeNation, skirmish.Money, skirmish.UnitCap);
            CurrentCircle.NationCurrent = NationName.Red;
        }

        public void NewSkirmishGame(ContentManager content, GameWindow windowGame, string mapName, List<NationName> nationName, 
                                    List<TeamName> teamName, List<TypeNation> typeNation, int[] teams, int moneys, int maxcharacter)
        {
            NewGame(content, windowGame, mapName, nationName, teamName, typeNation, moneys, maxcharacter);
            
        }

        public void NewGame(ContentManager content, GameWindow windowGame, string mapName, List<NationName> nationName, List<TeamName> teamName, List<TypeNation> typeNation, int moneys, int maxcharacter)
        {
            this.Map.InitNewMap(content, windowGame, mapName);

            // Bắt sự kiện thay đổi list building từ map
            this.Map.EventChangeListBuilding += new MapWithCell.EvenHandleChangeListBuilding(EventListBuildingChange);
            // Bắt sự kiện thay đổi list character từ map
            this.Map.EventChangeListCharacter += new MapWithCell.EvenHandleChangeListCharacter(EventListCharacterChange);
            // Bắt sự kiện mua character
            this.Map.EventBuyCharacter +=new MapWithCell.EventHandleBuyCharacter(EventBuyCharacter);

            this._maxMoney = moneys;
            this._unitMaxCharacter = maxcharacter;
            this._isFighting = true;
            this.ListNation = new List<Nation>();
            this.ListBuilding = new List<Building>();
            
            this.ListNationName = nationName;
            this.ListTeamName = teamName;
            this.ListTypeNation = typeNation;

            
            Nation tempNation = null;
            for (int i = 0; i < teamName.Count; i++)
            {
                switch (ListTypeNation[i])
                {
                    case TypeNation.Computer:
                        tempNation = new ComputerNation(content, new Vector2(), new Vector2(), ListNationName[i], ListTeamName[i], MaxMoney, UnitMaxCharacter);
                        break;
                    case TypeNation.Player:
                        tempNation = new PlayerNation(content, new Vector2(), new Vector2(), ListNationName[i], ListTeamName[i], MaxMoney, UnitMaxCharacter);
                        break;
                }

                ListNation.Add(tempNation);
                
                // Bắt sự kiện khi có 1 đội chiếm được building mới.
                ListNation[ListNation.IndexOf(tempNation)].OccupiedBuilding += new EventHandler(Battle_OccupiedBuilding);
            }
            this.InitAllBuildingAndKing(content);
            this.Map.ListBuilding = this.ListBuilding;
            for (int i = 0; i < Map.ListBuilding.Count; i++)
            {
                for (int j = 0; j < Map.ListBuilding[i].ListIndexCellUse.Count; j++)
                {
                    Map.Cells[(int)Map.ListBuilding[i].ListIndexCellUse[j].X, (int)Map.ListBuilding[i].ListIndexCellUse[j].Y].IsUsed = Map.ListBuilding[i].MyIndexNation;
                }
            }
            for (int i = 0; i < ListNation.Count; i++)
            {
                this.Map.ListCharacter.AddRange((List<Character>)ListNation[i].CharacterOwner);
            }
            // Bắt các sự kiện của nhân vật phát sinh ra.
            Map.CaptureEventFromCharacter();
            Map.CaptureEvenFromBuilding();
            Map.MState = this.MState;
            Map.ListNationName = this.ListNationName;
            Map.ListTeamName = this.ListTeamName;
            timerCount.Start();
        }

        // Xử lý sự kiện khi có 1 đội nào đó chiếm được bất kỳ 1 building mới nào.
        public void Battle_OccupiedBuilding(object sender, EventArgs e)
        {
            
        }

        public void InitAllBuildingAndKing(ContentManager content)
        {
            for (int i = 0; i < this.ListNation.Count; i++)
            {
                for (int j = 0; j < this.Map.ListInfoAllBuilding.Count; j++)
                {
                    if (CompareEnumNationNameVSStringNationName(ListNation[i].NationName, Map.ListInfoAllBuilding[j].teamName))
                    {
                        Building tempBuilding = new Building();
                        Vector2 tempPosition = new Vector2(Map.ListInfoAllBuilding[j].positionInMatrix.Y * MapWithCell.CELL_WIDTH, Map.ListInfoAllBuilding[j].positionInMatrix.X * MapWithCell.CELL_HEIGHT);
                        switch (Map.ListInfoAllBuilding[j].typeBuilding)
                        { 
                            case "House":
                                tempBuilding = new House(content, Map.ListInfoAllBuilding[j].listTextures.ToArray(), ListNation[i].NationName , tempPosition, -tempPosition,
                                                        new Vector2(MapWithCell.CELL_WIDTH * Map.InfoMapCurrent.multipleCellOfHouse.X, MapWithCell.CELL_HEIGHT * Map.InfoMapCurrent.multipleCellOfHouse.Y));
                                tempBuilding.SetListIndexCellUse(Map.InfoMapCurrent.dimensionMap, Map.ListInfoAllBuilding[j].positionInMatrix, Map.InfoMapCurrent.multipleCellOfHouse);
                                break;
                            case "Castle":
                                tempBuilding = new Castle(content, Map.ListInfoAllBuilding[j].listTextures.ToArray(), ListNation[i].NationName, tempPosition, -tempPosition,
                                                    new Vector2(MapWithCell.CELL_WIDTH * Map.InfoMapCurrent.multipleCellOfCastle.X, MapWithCell.CELL_HEIGHT * Map.InfoMapCurrent.multipleCellOfCastle.Y));
                                tempBuilding.SetListIndexCellUse(Map.InfoMapCurrent.dimensionMap , Map.ListInfoAllBuilding[j].positionInMatrix, Map.InfoMapCurrent.multipleCellOfCastle);       
                                break;
                        }
                        tempBuilding.ListChangeColor = Map.ListInfoAllBuilding[j].listColorIsChanged;
                        tempBuilding.SetColorAfterNation(Map.ListInfoAllBuilding[j].listColorIsChanged, ListNation[i].NationName);
                        Map.SetCellUsed(tempBuilding.ListIndexCellUse, tempBuilding.MyIndexNation);
                        this.ListBuilding.Add(tempBuilding);
                        this.ListNation[i].BuildingOwner.Add(tempBuilding);

                        if (tempBuilding is Castle)
                        {
                            this.ListNation[i].CharacterOwner.Add(tempBuilding.NewCharacter(content, CharacterName.King, tempPosition, -tempPosition, tempBuilding.MyNationName));
                            this.ListNation[i].CharacterOwner[this.ListNation[i].CharacterOwner.Count - 1].SetViewPort(MapWithCell.CELL_WIDTH, MapWithCell.CELL_HEIGHT);
                            this.ListNation[i].CharacterOwner[this.ListNation[i].CharacterOwner.Count - 1].Cells = Map.Cells;
                        }
                    }
                }
            }
        }

        public bool CompareEnumNationNameVSStringNationName(NationName nationname, string strnationname)
        {
            switch (nationname)
            {
                case NationName.Red:
                    if (strnationname == "Red")
                    {
                        return true;
                    }
                    break;
                case NationName.Green:
                    if (strnationname == "Green")
                    {
                        return true;
                    }
                    break;
                case NationName.Blue:
                    if (strnationname == "Blue")
                    {
                        return true;
                    }
                    break;
                case NationName.Black:
                    if (strnationname == "Black")
                    {
                        return true;
                    }
                    break;
                case NationName.None:
                    if (strnationname == "None")
                    {
                        return true;
                    }
                    break;
               
            }
            return false;
        }

        public override void Update(GameTime gameTime)
        {

            Map.Update(gameTime);
            for (int i = 0; i < ListNation.Count; i++)
            {
                    ListNation[i].Update(gameTime);
            }
            // Option panel
            Map.PanelGame.Update(gameTime);

        }
        
        public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            Map.Draw(gameTime, spriteBatch);
            for (int i = 0; i < ListNation.Count; i++)
            {
                if (IsFighting)
                    ListNation[i].Draw(gameTime, spriteBatch);
            }
            // Panel game
            Map.PanelGame.Draw(gameTime, spriteBatch);
            //////////////

            if (ListNation.Count == 1 && Map.PanelGame.PlayingMenu.IsActive==false)
            {
                countDrawNewTurn++;
                if (countDrawNewTurn == 10)
                {
                    countDrawNewTurn = 0;
                    CurrentCircle.IsChangeNation = false;
                }
                string newTurn = ListNation[0].NationName.ToString() + " Won";
                Vector2 FontOrigin = MyFont.FontCourierNew.MeasureString(newTurn) / 2;
                Vector2 position = new Vector2(spriteBatch.GraphicsDevice.Viewport.Width / 2,
                                               spriteBatch.GraphicsDevice.Viewport.Height / 2);
                Color color = new Color();
                switch (CurrentCircle.NationCurrent)
                {
                    case NationName.Black:
                        color = Color.Black;
                        break;
                    case NationName.Red:
                        color = Color.Red;
                        break;
                    case NationName.Green:
                        color = Color.Green;
                        break;
                    case NationName.Blue:
                        color = Color.Blue;
                        break;
                }
                spriteBatch.DrawString(MyFont.FontCourierNew, newTurn, position, color,
                                    0, FontOrigin, 2.0f, SpriteEffects.None, 1.0f);
            }

            if (CurrentCircle.IsChangeNation)
            {
                countDrawNewTurn++;
                if (countDrawNewTurn == 10)
                {
                    countDrawNewTurn = 0;
                    CurrentCircle.IsChangeNation = false;
                }
                string newTurn = "New Turn";
                Vector2 FontOrigin = MyFont.FontCourierNew.MeasureString(newTurn) / 2;
                Vector2 position = new Vector2(spriteBatch.GraphicsDevice.Viewport.Width / 2,
                                               spriteBatch.GraphicsDevice.Viewport.Height / 2);
                Color color = new Color();
                switch (CurrentCircle.NationCurrent)
                {
                    case NationName.Black:
                        color = Color.Black;
                        break;
                    case NationName.Red:
                        color = Color.Red;
                        break;
                    case NationName.Green:
                        color = Color.Green;
                        break;
                    case NationName.Blue:
                        color = Color.Blue;
                        break;
                }
                spriteBatch.DrawString(MyFont.FontCourierNew, newTurn, position, color,
                                    0, FontOrigin, 2.0f, SpriteEffects.None, 1.0f);
            }
        }
    }
}
